using InternalEditor;
using System.Collections;
using UnityEditor;
using UnityEditor.Animations;
using UnityEditorInternal;
using UnityEngine;

namespace GameDesigner
{
    internal class LayerView
    {
        private int m_LastSelectedIndex;
        private int m_SelectedLayerIndex = 0;
        private static Styles s_Styles;
        private ReorderableList m_LayerList;
        private Vector2 m_LayerScroll;
        private RenameOverlayProxy m_RenameOverlay;
        private bool m_HadKeyFocusAtMouseDown = false;

        public int selectedLayerIndex
        {
            get
            {
                if (StateMachineWindow.support != null && m_SelectedLayerIndex >= StateMachineWindow.support.controller.layers.Length)
                {
                    m_SelectedLayerIndex = StateMachineWindow.support.controller.layers.Length - 1;
                    m_LayerList.index = m_SelectedLayerIndex;
                    StateMachineWindow.Singleton.ResetUI();
                }
                return m_SelectedLayerIndex;
            }
            set
            {
                m_SelectedLayerIndex = value;
                m_LayerList.index = m_SelectedLayerIndex;
                StateMachineWindow.Singleton.ResetUI();
            }
        }

        public RenameOverlayProxy renameOverlay
        {
            get
            {
                if (m_RenameOverlay == null)
                    m_RenameOverlay = new RenameOverlayProxy();
                return m_RenameOverlay;
            }
        }

        public void ResetUI()
        {
            if (StateMachineWindow.support == null || StateMachineWindow.support.controller == null || StateMachineWindow.support.controller.layers == null)
            {
                m_SelectedLayerIndex = 0;
                m_LastSelectedIndex = -1;
                m_LayerList.index = selectedLayerIndex;
            }
            else
            {
                if (selectedLayerIndex > StateMachineWindow.support.controller.layers.Length)
                    m_SelectedLayerIndex = StateMachineWindow.support.controller.layers.Length - 1;
                if (m_LastSelectedIndex > StateMachineWindow.support.controller.layers.Length)
                    m_LastSelectedIndex = StateMachineWindow.support.controller.layers.Length - 1;
                m_LayerList.index = m_SelectedLayerIndex;
                m_LayerScroll = Vector2.zero;
            }
        }

        public void Init()
        {
            if (m_LayerList != null)
                return;
            m_LayerList = new ReorderableList(StateMachineWindow.support != null ? (IList)StateMachineWindow.support.controller.layers : new StateLayer[0], typeof(StateLayer), true, false, false, false);
            m_LayerList.onReorderCallback = new ReorderableList.ReorderCallbackDelegate(OnReorderLayer);
            m_LayerList.drawElementCallback = new ReorderableList.ElementCallbackDelegate(OnDrawLayer);
            m_LayerList.drawElementBackgroundCallback = new ReorderableList.ElementCallbackDelegate(OnDrawLayerBackground);
            m_LayerList.onMouseUpCallback = new ReorderableList.SelectCallbackDelegate(OnMouseUpLayer);
            m_LayerList.showDefaultBackground = false;
            m_LayerList.onSelectCallback = new ReorderableList.SelectCallbackDelegate(OnSelectLayer);
            m_LayerList.index = selectedLayerIndex;
            m_LayerList.headerHeight = 0.0f;
            m_LayerList.footerHeight = 0.0f;
            m_LayerList.elementHeight = 40f;
        }

        private void OnReorderLayer(ReorderableList reorderablelist)
        {
            var list = reorderablelist.list as StateLayer[];
            selectedLayerIndex = reorderablelist.index;
            StateMachineWindow.support.controller.layers = list;
            StateMachineWindow.Singleton.ResetUI();
        }

        private void DeleteLayer() => OnRemoveLayer(m_LayerList.index);

        private void OnDrawLayer(Rect rect, int index, bool selected, bool focused)
        {
            var current = Event.current;
            if (current.type == EventType.MouseUp && current.button == 1 && rect.Contains(current.mousePosition))
            {
                var genericMenu = new GenericMenu();
                genericMenu.AddItem(EditorGUIUtility.TrTextContent("Delete"), false, new GenericMenu.MenuFunction(this.DeleteLayer));
                genericMenu.ShowAsContext();
                Event.current.Use();
            }

            var layer = m_LayerList.list[index] as StateLayer;
            rect.yMin += 4f;
            rect.yMax -= 4f;
            var vector2_1 = EditorStyles.iconButton.CalcSize(s_Styles.settingsIcon);
            var rect1 = new Rect((float)(rect.xMax - (double)vector2_1.x - 4f), rect.yMin + 1f, vector2_1.x, rect.height - 16f);

            if (GUI.Button(rect1, s_Styles.settingsIcon, EditorStyles.iconButton))
            {
                var buttonRect = rect1;
                buttonRect.x += 15f;
                if (LayerSettingsWindow.ShowAtPosition(buttonRect, layer))
                    GUIUtility.ExitGUI();
            }

            var position2 = Rect.MinMaxRect(rect.xMin, rect.yMin, rect1.xMin - 4f, rect.yMax - 16f);
            float left = s_Styles.label.padding.left;
            var rect2 = Rect.MinMaxRect(rect.xMin + left, rect.yMax - 11f, rect1.xMax, rect.yMax - 9f);
            if (renameOverlay.IsRenaming() && renameOverlay.userData == index && !renameOverlay.isWaitingForDelay)
            {
                if (position2.width >= 0.0 && position2.height >= 0.0)
                {
                    position2.x -= 2f;
                    renameOverlay.editFieldRect = position2;
                }
                if (!renameOverlay.OnGUI())
                    RenameEnd();
            }
            else if (Event.current.type == EventType.Repaint)
                s_Styles.label.Draw(position2, layer.name, false, false, selected, focused);

            EditorGUI.DrawRect(rect2, s_Styles.progressBackground);
            rect2.width *= layer.GetLayerWeight();
            EditorGUI.DrawRect(rect2, EditorApplication.isPlaying ? s_Styles.progressLiveLink : s_Styles.progressEdit);
        }

        private void OnDrawLayerBackground(Rect rect, int index, bool selected, bool focused)
        {
            if (Event.current.type != EventType.Repaint)
                return;
            s_Styles.layerBackground.Draw(rect, false, false, false, false);
            Rect position = rect;
            --position.yMax;
            s_Styles.elementBackground.Draw(position, false, selected, selected, focused);
        }

        private void OnMouseUpLayer(ReorderableList list)
        {
            if (m_HadKeyFocusAtMouseDown && list.index == m_LastSelectedIndex && Event.current.button == 0)
                renameOverlay.BeginRename((list.list[list.index] as StateLayer).name, list.index, 0.1f);
            m_LastSelectedIndex = list.index;
        }

        private void OnSelectLayer(ReorderableList list)
        {
            if (selectedLayerIndex == list.index)
                return;
            selectedLayerIndex = list.index;
            StateMachineWindow.Singleton.ResetUI();
        }

        private void RenameEnd()
        {
            if (renameOverlay.userAcceptedRename)
            {
                string name1 = string.IsNullOrEmpty(renameOverlay.name) ? renameOverlay.originalName : renameOverlay.name;
                if (name1 != renameOverlay.originalName)
                {
                    var animatorControllerLayer = m_LayerList.list[renameOverlay.userData] as StateLayer;
                    animatorControllerLayer.name = name1;
                    StateMachineWindow.support.controller.layers = m_LayerList.list as StateLayer[];
                }
            }
            m_LayerList.GrabKeyboardFocus();
            renameOverlay.Clear();
        }

        public void OnToolbarGUI()
        {
            if (s_Styles == null)
                s_Styles = new Styles();
            using (new EditorGUI.DisabledScope(StateMachineWindow.support == null))
            {
                var rect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.toolbar);
                var vector2 = EditorStyles.iconButton.CalcSize(s_Styles.addIcon);
                var rect1 = new Rect(rect.xMax - vector2.x - 10f, rect.y + (int)((rect.height / 2.0) - (vector2.y / 2.0)), vector2.x, vector2.y);
                if (GUI.Button(rect1, s_Styles.addIcon, EditorStyles.iconButton))
                {
                    var host = StateMachineWindow.support.controller;
                    host.AddNewLayer();
                    m_LayerList.list = host.layers;
                    m_LayerList.index = host.layers.Length - 1;
                    selectedLayerIndex = m_LayerList.index;
                    if (renameOverlay.IsRenaming())
                        RenameEnd();
                    renameOverlay.BeginRename(host.layers[selectedLayerIndex].name, selectedLayerIndex, 0.1f);
                }
            }
        }

        private void KeyboardHandling()
        {
            if (!m_LayerList.HasKeyboardControl())
                return;
            Event current = Event.current;
            switch (current.type)
            {
                case EventType.KeyDown:
                    switch (Event.current.keyCode)
                    {
                        case KeyCode.Delete:
                            current.Use();
                            OnRemoveLayer(m_LayerList.index);
                            return;
                        case KeyCode.Home:
                            current.Use();
                            m_LayerList.index = m_SelectedLayerIndex = 0;
                            StateMachineWindow.Singleton.ResetUI();
                            return;
                        case KeyCode.End:
                            current.Use();
                            m_LayerList.index = m_SelectedLayerIndex = m_LayerList.count - 1;
                            StateMachineWindow.Singleton.ResetUI();
                            return;
                        default:
                            return;
                    }
                case EventType.ExecuteCommand:
                    if (!(current.commandName == "SoftDelete") && !(current.commandName == "Delete"))
                        break;
                    current.Use();
                    OnRemoveLayer(m_LayerList.index);
                    break;
            }
        }

        protected void OnRemoveLayer(int layerIndex)
        {
            StateMachineWindow.support.controller.RemoveLayers(layerIndex);
            ResetUI();
            StateMachineWindow.Singleton.ResetUI();
        }

        public void OnEvent() => renameOverlay.OnEvent();

        public void OnGUI(Rect rect)
        {
            if (s_Styles == null)
                s_Styles = new Styles();
            KeyboardHandling();
            if (StateMachineWindow.support != null)
                m_LayerList.list = StateMachineWindow.support.controller.layers;
            else if (m_LayerList.list.Count != 0)
                m_LayerList.list = new StateLayer[0];
            var current = Event.current;
            if (current.type == EventType.MouseDown && rect.Contains(current.mousePosition))
                m_HadKeyFocusAtMouseDown = m_LayerList.HasKeyboardControl();
            m_LayerScroll = GUILayout.BeginScrollView(m_LayerScroll);
            m_LayerList.DoLayoutList();
            GUILayout.EndScrollView();
            GUILayout.FlexibleSpace();
        }

        private class Styles
        {
            public readonly GUIContent addIcon = EditorGUIUtility.IconContent("CreateAddNew");
            public readonly GUIContent settingsIcon = EditorGUIUtility.IconContent("SettingsIcon");
            public readonly GUIContent settings = EditorGUIUtility.TrTextContent("Settings", "Click to change layer settings.");
            public readonly GUIStyle elementBackground = "RL Element";
            public readonly GUIStyle label = nameof(label);
            public readonly GUIStyle layerBackground = "AnimItemBackground";
            public readonly GUIStyle layerLabel = new GUIStyle("miniLabel");
            public readonly GUIContent sync = EditorGUIUtility.TrTextContent("S", "Layer is a Synchronized layer.");
            public readonly GUIContent syncTime = EditorGUIUtility.TrTextContent("S+T", "Layer is a Synchronized layer and will take control of the duration for this Synced Layer.");
            public readonly GUIContent ik = EditorGUIUtility.TrTextContent("IK", "When active, the layer will have an IK pass when evaluated. It will trigger an OnAnimatorIK callback.");
            public readonly GUIContent additive = EditorGUIUtility.TrTextContent("A", "Additive Layer.");
            public readonly GUIContent mask = EditorGUIUtility.TrTextContent("M", "Layer has an AvatarMask.");
            public readonly GUIContent maskWarningIcon = EditorGUIUtility.IconContent("console.warnicon.sml");
            public readonly GUIContent maskWarning = EditorGUIUtility.TrTextContent("M", "Character orientation may be erroneous for humanoid motion if there is an AvatarMask on the default layer.  Consider not using a mask for the default layer.");
            public readonly Color progressBackground = new Color(0.33f, 0.33f, 0.33f);
            public readonly Color progressLiveLink = new Color(0.29803923f, 0.69803923f, 1f);
            public readonly Color progressEdit = new Color(0.54509807f, 0.54509807f, 0.54509807f);

            public Styles()
            {
                settingsIcon.tooltip = settings.tooltip;
                maskWarningIcon.tooltip = maskWarning.tooltip;
                layerLabel.alignment = TextAnchor.MiddleCenter;
                layerLabel.fontStyle = FontStyle.Bold;
                layerLabel.padding = new RectOffset(0, 0, 0, 0);
                layerLabel.margin = new RectOffset(0, 0, 0, 0);
            }
        }
    }
}